/**********************************************************************
*  Copyright (c) 2007 - Victor Jacobs - victor.jacobs@gmail.com
*
*  Permission is hereby granted, free of charge, to any person
*  obtaining a copy of this software and associated documentation
*  files (the "Software"), to deal in the Software without
*  restriction, including without limitation the rights to use,
*  copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the
*  Software is furnished to do so, subject to the following
*  conditions:
*
*  The above copyright notice and this permission notice shall be
*  included in all copies or substantial portions of the Software.
*
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
*  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
*  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
*  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
*  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
*  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
*  OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/

using System;
using System.Collections;

namespace Vj.GA
{
    // (dynamic) function to use for fitness
    public delegate double FitFunc(double[] x);

    public enum TerminationOperators
    {
        GenerationNumber, EvolutionTime, PopulationConvergence,
        GeneConvergence, FitnessConvergence
    }

    /// <summary>
    /// Summary description for myGA.
    /// </summary>
    public class GeneticAlg
    {
        private int generationCount = 0;
        private Population population;

        //private bool stop = false;
        //private bool pause = false;	

        public GeneticAlg() { }

        public Population Population
        {
            get { return population; }
        }

        static private FitFunc fitnessFunction;
        public FitFunc FitnessFunction
        {
            get
            { return fitnessFunction; }
            set
            { fitnessFunction = value; }
        }

        public int PopSize
        {
            get { return population.PopSize; }
        }

        public void Initiate(int popSize, int alleleLength, int numOfAlleles)
        {
            population = new Population(popSize, alleleLength, numOfAlleles);
        }

        public void SetOperators(SelectionOperators selOp, MutationOperators muOp, 
            CrossoverOperators coOp, ReplacementOperators replOp, bool elitism)
        {
            population.SetOperators(selOp, muOp, coOp, replOp, elitism);
        }

        public void DoStep(int popSize, float muRate, float selRate)
        {
            population.DoGeneration(muRate, selRate);
            population.Evaluate(fitnessFunction);
            population.CalculateStats();
            generationCount++;
        }

        public void DoEvolve(int maxGens, float muRate, float selRate)
        {
            for (int i = 0; i < maxGens; i++)
            {
                population.DoGeneration(muRate, selRate);
                population.Evaluate(fitnessFunction);
                population.CalculateStats();
                generationCount++;
            }
        }

        public override string ToString()
        {
            string output = "Generation: " + generationCount + "\r\n";
            output += population.ToString();
            return output + "\r\n";
        }

        public Population GetPopulation()
        {
            return population;
        }

        public void Stop()
        {
        }

        public void Pause()
        {
        }
    }
}
